package LAAMI;

import repast.simphony.engine.environment.RunEnvironment;
import repast.simphony.engine.schedule.ScheduledMethod;
import repast.simphony.random.RandomHelper;

import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;

public class Investor {
	private double histVolatility;
	// Patience is the minimum length of days to calculate historical
	// volatility, which is given by a random integer between 5 and 45 (days).
	private int patience;
	// Judgment is the trader’s personal adjustment of his experience in
	// historical volatility band, which is given by a random number between
	// 0.5 and 1.5 at the beginning of simulation and remains constant.
	private double judgement;
	// Every agent has to calculate one call price and one ask price for every
	// one of the 5 strike prices
	private double callPrice;
	private double askPrice;
	// We specify a band of volatility for each agent
	private double minVolatility;
	private double maxVolatility;
	// We take the European call value for Black-Scholes
	private boolean call = true;
	private double maturity;
	

	public Investor(int patience, double judgement, double maturity) {
		setPatience(patience);
		setJudgement(judgement);
		setMaturity(maturity);
	}

	// After the 50th day, agents make their estimation for the historical
	// volatility, they construct their volatility band and set the range
	// of prices they are willing to trade.
	@ScheduledMethod(start = 51, interval = 1, priority = 3)
	public void step() {
		int curDay = (int) RunEnvironment.getInstance().getCurrentSchedule()
				.getTickCount();
		if (curDay >= 51) {
			setHistoricalVolatility(curDay);
			setVolatilityBand();
		}

		for (int i = 1; i <= 5; i++) {
			setHighestPrice();
			setLowestPrice();
		}
	}

	// For a range of "obsWindow" days in the past, agents take as historical
	// volatility the standard deviation of the daily change of prices
	// multiplied by sqrt(252), where 252 is the number of trading days of a
	// year
	public void setHistoricalVolatility(int curDay) {
		DescriptiveStatistics Stats = new DescriptiveStatistics();
		int obsWindow = RandomHelper.nextIntFromTo(patience, curDay);

		for (int i = 1; i < obsWindow; i++) {
			double priceNew = (Double) LAAMIBuilder.getStockmarket().priceList
					.get(curDay - i);
			double priceOld = (Double) LAAMIBuilder.getStockmarket().priceList
					.get(curDay - (i + 1));

			double dailyChange = (double) (priceNew - priceOld) / priceOld;
			Stats.addValue(dailyChange);
		}
		// are we sure about that? cause the historical volatilities produced
		// are from 0.09 to 0.19 when the volatility for the stock market price
		// is 0.3
		double StdDev = Stats.getStandardDeviation();

		// The annualized volatility sigma
		double sigma = StdDev * Math.sqrt(252);

		// Time horizon T in years
		double T = (double) patience / 252;
		double sigmaT;

		// 1st way: Generalized volatility σT for time horizon T in years
		// sigmaT = (double) (sigma * Math.sqrt(T));

		// 2nd way: Lévy stability exponent
		// double alpha = 1.8;
		// sigmaT = Math.pow(T, 1.0 / alpha) * sigma;

		// 3rd way: We use the annualized volatility
		sigmaT = sigma;

		setHistVolatility(sigmaT);

//		System.out.print(histVolatility + "\t");
	}

	public void setVolatilityBand() {
		setMinVolatility(histVolatility - histVolatility * judgement);
		if (minVolatility <= 0)
			setMinVolatility(0.01);
		setMaxVolatility(histVolatility + histVolatility * judgement);
		if (maxVolatility >= 1)
			setMaxVolatility(0.99);
	}

	// We calculate the BlackScholes formula 10 times to find one low price
	// and one high price for each one of the 5 strike prices. In that
	// way we create a range of trading prices for each agent.

	public void setHighestPrice() {
		double stockPrice = LAAMIBuilder.getStockmarket().getPrice();
		double strikePrice = LAAMIBuilder.getStockmarket().getStrikePrice();
		setCallPrice( BlackScholes.getPrice(call, stockPrice, strikePrice,
				maxVolatility));
	}

	public void setLowestPrice() {
		double stockPrice = LAAMIBuilder.getStockmarket().getPrice();
		double strikePrice = LAAMIBuilder.getStockmarket().getStrikePrice();
		setAskPrice( BlackScholes.getPrice(call, stockPrice, strikePrice,
				minVolatility));
	}

	/*-------------setters/getters--------------------*/
	public double getHistVolatility() {
		return histVolatility;
	}

	public void setHistVolatility(double h) {
		histVolatility = h;
	}

	public int getPatience() {
		return patience;
	}

	public void setPatience(int p) {
		patience = p;
	}

	public double getJudgement() {
		return judgement;
	}

	public void setJudgement(double j) {
		judgement = j;
	}

	public double getMinVolatility() {
		return minVolatility;
	}

	public void setMinVolatility(double m) {
		minVolatility = m;
	}

	public double getMaxVolatility() {
		return maxVolatility;
	}

	public void setMaxVolatility(double m) {
		maxVolatility = m;
	}

	public double getCallPrice() {
		return callPrice;
	}

	public void setCallPrice(double c) {
		callPrice = c;
	}

	public double getAskPrice() {
		return askPrice;
	}

	public void setAskPrice(double a1) {
		askPrice = a1;
	}

	public double getMaturity() {
		return maturity;
	}

	public void setMaturity(double maturity) {
		this.maturity = maturity;
	}
}
